package com.dsteiner.xelavos.client.controller;

import static com.dsteiner.widgets.client.util.Validator.BIRTHDAY_VALIDATOR;
import static com.dsteiner.widgets.client.util.Validator.EMAIL_VALIDATOR;
import static com.dsteiner.widgets.client.util.Validator.NOT_NULL_VALIDATOR;
import static com.dsteiner.widgets.client.util.Validator.PSWD_VALIDATOR;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Date;

import com.dsteiner.widgets.client.IDateUtil;
import com.dsteiner.widgets.client.IJsUtil;
import com.dsteiner.widgets.client.JsUtil;
import com.dsteiner.widgets.client.StringUtil;
import com.dsteiner.widgets.client.Widgets.IButton;
import com.dsteiner.widgets.client.Widgets.IHTML;
import com.dsteiner.widgets.client.Widgets.ILazyWidget;
import com.dsteiner.widgets.client.Widgets.IWidget;
import com.dsteiner.widgets.client.Widgets.SelectionInput;
import com.dsteiner.widgets.client.Widgets.WidgetListenerAdapter;
import com.dsteiner.widgets.client.domain.ModelObject;
import com.dsteiner.widgets.client.event.EventManager;
import com.dsteiner.widgets.client.event.MessageEvent;
import com.dsteiner.widgets.client.model.PopupOverlayModel;
import com.dsteiner.widgets.client.model.PrefilledTextBoxModel;
import com.dsteiner.widgets.client.rpc.CrudResult;
import com.dsteiner.widgets.client.util.ValidationResults;
import com.dsteiner.xelavos.client.AuthenticationWidget.CreateAccountModel;
import com.dsteiner.xelavos.client.constants.Constants;
import com.dsteiner.xelavos.client.domain.User;
import com.dsteiner.xelavos.client.model.AuthenticationModel;
import com.dsteiner.xelavos.client.rpc.DataServiceAsync;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class CreateAccountController {

	private PrefilledTextBoxModel firstNameTextBoxModel;
	private PrefilledTextBoxModel lastNameTextBoxModel;
	private PrefilledTextBoxModel emailTextBoxModel;
	private PrefilledTextBoxModel passwordTextBoxModel;
	private PrefilledTextBoxModel passwordConfirmTextBoxModel;
	private AuthenticationModel authenticationModel;
	private PrefilledTextBoxModel birthdayTextBoxModel;
	private boolean isCreatingAccount;
	private SelectionInput termsCheckBox;
	private SelectionInput femaleRadioButton;
	private SelectionInput maleRadioButton;
	private CreateAccountModel createAccountModel;
	private IHTML messageHtml;
	private PopupOverlayModel createAccountPopupModel;
	private SelectionInput receiveReportCheckBox;
	private IJsUtil jsUtil;
	private DataServiceAsync dataService;
	private IDateUtil dateUtil;
	private EventManager eventManager;

	public void registerAuthenticationModel(AuthenticationModel authenticationModel) {
		this.authenticationModel = authenticationModel;
	}

	public void registerBirthdayTextBoxModel(PrefilledTextBoxModel birthdayTextBoxModel) {
		this.birthdayTextBoxModel = birthdayTextBoxModel;
	}

	public void registerCreateAccountButton(IButton createAccountButton) {
		createAccountButton.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event) {
				if(!isCreatingAccount){
					jsUtil.trackEvent(Constants.CAT_ACCOUNT, Constants.ACT_CLICKED_CREATE_BUTTON);
					doCreateAccount();
				}
			}
		});
	}

	public void registerCreateAccountModel(CreateAccountModel createAccountModel) {
		this.createAccountModel = createAccountModel;
		createAccountModel.addPropertyChangeListener("message", new PropertyChangeListener(){
			public void propertyChange(PropertyChangeEvent evt) {
				updateMessageHtml();
			}
		});
	}

	public void registerCreateAccountPopupModel(PopupOverlayModel createAccountPopupModel) {
		this.createAccountPopupModel = createAccountPopupModel;
	}

	public void registerCreateAccountWidget(ILazyWidget createAccounWidget) {
		createAccounWidget.addWidgetListener(new WidgetListenerAdapter(){
			@Override
			public void onAttach(IWidget widget) {
				isCreatingAccount = false;
				createAccountModel.setMessage(null);
				passwordTextBoxModel.setText(null);
				passwordConfirmTextBoxModel.setText(null);
				firstNameTextBoxModel.setText(null);
				lastNameTextBoxModel.setText(null);
				birthdayTextBoxModel.setText(null);
				emailTextBoxModel.setText(null);
				termsCheckBox.setChecked(false);
			}
		});
	}

	public void registerDataService(DataServiceAsync dataService) {
		this.dataService = dataService;
	}

	public void registerDateUtil(IDateUtil dateUtil) {
		this.dateUtil = dateUtil;
	}

	public void registerEmailTextBox(PrefilledTextBoxModel emailTextBoxModel) {
		this.emailTextBoxModel = emailTextBoxModel;
	}

	public void registerEventManager(EventManager eventManager) {
		this.eventManager = eventManager;
	}

	public void registerFemaleRadioButton(SelectionInput femaleRadioButton) {
		this.femaleRadioButton = femaleRadioButton;
	}

	public void registerFirstNameTextBox(PrefilledTextBoxModel firstNameTextBoxModel) {
		this.firstNameTextBoxModel = firstNameTextBoxModel;
	}

	public void registerJsUtil(IJsUtil jsUtil) {
		this.jsUtil = jsUtil;
	}

	public void registerLastNameTextBox(PrefilledTextBoxModel lastNameTextBoxModel) {
		this.lastNameTextBoxModel = lastNameTextBoxModel;
	}

	public void registerMaleRadioButton(SelectionInput maleRadioButton) {
		this.maleRadioButton = maleRadioButton;
	}

	public void registerMessageHtml(IHTML messageHtml) {
		this.messageHtml = messageHtml;
	}

	public void registerPasswordConfirmTextBox(PrefilledTextBoxModel passwordConfirmTextBoxModel) {
		this.passwordConfirmTextBoxModel = passwordConfirmTextBoxModel;
	}

	public void registerPasswordTextBox(PrefilledTextBoxModel passwordTextBoxModel) {
		this.passwordTextBoxModel = passwordTextBoxModel;
	}

	public void registerReceiveReportCheckBox(SelectionInput receiveReportCheckBox) {
		this.receiveReportCheckBox = receiveReportCheckBox;
		receiveReportCheckBox.setChecked(true);
	}

	public void registerTermsCheckBox(SelectionInput termsCheckBox) {
		this.termsCheckBox = termsCheckBox;
	}

	private void doCreateAccount() {
		String passwordConfirm = passwordConfirmTextBoxModel.isEdited() ? passwordConfirmTextBoxModel.getText() : null;
		String password = passwordTextBoxModel.isEdited() ? passwordTextBoxModel.getText() : null;
		String firstName = firstNameTextBoxModel.isEdited() ? firstNameTextBoxModel.getText() : null;
		String lastName = lastNameTextBoxModel.isEdited() ? lastNameTextBoxModel.getText() : null;
		String email = emailTextBoxModel.isEdited() ? emailTextBoxModel.getText() : null;
		String birthday = birthdayTextBoxModel.isEdited() ? birthdayTextBoxModel.getText() : null;
		Date birthdayDate = dateUtil.parseDateSpanish(birthday);
		Integer gender = null;
		if(maleRadioButton.isChecked())
			gender = User.GENDER_MALE;
		if(femaleRadioButton.isChecked())
			gender = User.GENDER_FEMALE;
		Boolean termsChecked = termsCheckBox.isChecked() ? true : null;
		
		final User user = new User();
		BIRTHDAY_VALIDATOR.setDateUtil(dateUtil);
		
		ValidationResults results = new ValidationResults()
		.add(EMAIL_VALIDATOR.validate(email))
		.add(PSWD_VALIDATOR.validate(password, passwordConfirm))
		.add(BIRTHDAY_VALIDATOR.validate(birthday))
		.add(NOT_NULL_VALIDATOR.validate(gender, "selecione su sexo", "gender"))
		.add(NOT_NULL_VALIDATOR.validate(firstName, "ingrese su nombre", "firstName"))
		.add(NOT_NULL_VALIDATOR.validate(lastName, "ingrese su apellido", "lastName"))
		.add(NOT_NULL_VALIDATOR.validate(termsChecked, "accepte las condiciones de uso", "terms"));
		
		passwordConfirmTextBoxModel.setHasError(results.contains("passwordConfirm"));
		passwordTextBoxModel.setHasError(results.contains("password"));
		birthdayTextBoxModel.setHasError(results.contains("birthday"));
		emailTextBoxModel.setHasError(results.contains("email"));
		firstNameTextBoxModel.setHasError(results.contains("firstName"));
		lastNameTextBoxModel.setHasError(results.contains("lastName"));
		
		if(!results.isEmpty()){
			String validationMsg = results.getMessage();
			jsUtil.trackEvent(Constants.CAT_ACCOUNT, Constants.ACT_MSG_SHOWN, validationMsg);
			eventManager.fireEvent(new MessageEvent(validationMsg));
			return;
		}
		user.setBirthday(birthdayDate);
		user.setFirstName(firstName);
		user.setLastName(lastName);
		user.setJoinDate(new Date());
		user.setPassword(password);
		user.setEmail(email);
		user.setGender(gender);
		user.setReceiveReport(receiveReportCheckBox.isChecked());
		isCreatingAccount = true;
		authenticationModel.setMessage("crear cuenta....");
		createAccountPopupModel.setVisible(false);
		dataService.createModelObject(user, new AsyncCallback<CrudResult<ModelObject>>(){
			public void onFailure(Throwable caught) {
				caught.printStackTrace();
				authenticationModel.setMessage("crear cuenta fallo - intentalo de nuevo");
			}
			public void onSuccess(CrudResult result) {
				if(!StringUtil.isEmpty(result.getError())){
					authenticationModel.setMessage(result.getError());
				}
				else{
					authenticationModel.setMessage(null);
					User user = (User) result.getModelObject();
					authenticationModel.setUser(user);
					JsUtil.getInstance().trackGAVar(Constants.Util.getUserGAVar(user));
				}
			}
		});
	}

	private void updateMessageHtml() {
		String message = createAccountModel.getMessage();
		messageHtml.setVisible(message != null);
		messageHtml.setHTML(message);
	}

}
